lieoo's blog

escaping 的理解(Swift 4.0)

我所在的项目组 iOS 版本 App 进入收尾阶段,还是希望自己慢慢接触到 Swift,一点一点使用 Swift 重构甚至是重写。其中 “@escaping” 就是我遇到的问题之一,所以希望本篇文章作为自己的收获和笔记。

背景

先上段代码

这段代码作用于网络请求,自己想封装一下请求功能。

传参数为:URL 链接``请求参数

返回值为:成功请求的 JSON请求失败的 Error

报错的关键字 Closure use of non-escaping parameter ‘success’ may allow it to escape,Parameter ‘success’ is implicitly non-escaping.

什么是 @escaping (逃逸)

先来段英文定义解(zhuang)释(xia)下(bi)

If a closure is passed as an argument to a function and it is invoked after the function returns, the closure is escaping.

大意为:

如果一个闭包被作为一个参数传递给一个函数,并且在函数 return 之后才被唤起执行,那么这个闭包是逃逸闭包

Swift_Programming_Language/Closures

什么是 @non-escaping (非逃逸)

可以将 @non-escaping 理解为:

如果这个闭包是在这个函数结束前内被调用,就是非逃逸的即 @noescape

需要记住的一点是:
在 Swift 1.0 和 Swift 2.0 时代,@escaping 是默认的。如果知道这个闭包函数是非逃逸的,可以使用 @noescape 来标记函数。

但是在 Swift 3.0,则反之,如果知道这个闭包函数是逃逸的,就必须用 @escaping 标记他。

使用场景

在自己写 Swift 中最常见的闭包两个例子是:

使用 Alamofire 封装网络请求 -> 逃逸闭包 -> 需加 @escaping 关键字

使用 SnapKit 库布局 -> 非逃逸闭包 ->无需加任何关键字(默认即为非逃逸闭包)

*这里可以将逃逸闭包理解为异步操作,非逃逸闭包理解为同步操作。

注意事项

@escaping 逃逸闭包

  1. 访问属性或调用方法时必须加 self ,而且要注意循环引用问题

  2. 闭包在函数 return 之后执行,即异步执行

@noescape 非逃逸闭包

  1. 闭包中默认属性

  2. 闭包在函数返回之前执行,即同步执行

逃逸闭包与非逃逸闭包 目的是明确的告诉编译器:这里是@escaping,
即逃逸闭包,能够最大程度上对编译器编译优化。

解决

我所处的状态为逃逸闭包,所以要在闭包前加入@escaping即可解决此问题。